package com.me.supermario.entities;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.me.supermario.screens.Play;

public class Guscio extends Sprite {

	//IMPORTANTI
	private Vector2 velocity = new Vector2 ();
	private TiledMapTileLayer collisionLayer;
	protected Rectangle rect = new Rectangle ();
	private static Sprite sprite = new Sprite(new Texture("com/me/img/guscio.png"));
	private Player player;
	
	//ANIMAZIONI
	private static TextureAtlas guscioAtlas = new TextureAtlas("com/me/img/guscio.pack");
	private static Animation still = new Animation (1/2f, guscioAtlas.findRegions("still"));
	private static Animation left = new Animation (1/6f, guscioAtlas.findRegions("left"));
	private static Animation right = new Animation (1/6f, guscioAtlas.findRegions("right"));

	
	//VARIABILI FLOAT
	private float speed = 150, gravity = 200 * 1.8f, increment, animationTime = 0;
	private float oldSpeed;
	
	//VARIABILI BOOLEANE
	private boolean firstTime = true;	
	private boolean deadState;
	
	//STRINGHE E PROPRIETA' DEI TILE
	private String blockedKey = "blocked";
	private String mushBlockedKey = "blocked";

	//COSTRUTTORE
	public Guscio (TiledMapTileLayer collisionLayer, Player player) {
		super (still.getKeyFrame(0));
		this.collisionLayer = collisionLayer;
		this.player = player;
		
		still.setPlayMode(Animation.LOOP);
		left.setPlayMode(Animation.LOOP);
		right.setPlayMode(Animation.LOOP);
	}//costruttore
 
	public void draw (SpriteBatch spritebatch) {
		update(Gdx.graphics.getDeltaTime());
		super.draw(spritebatch);
	}//draw

	private void update(float delta) {
		//System.out.println ("entro in update");
		velocity.y -= gravity*delta;
		
		/*if (firstTime){
			//System.out.println ("entro in firsttime");
			velocity.x = -speed;
			firstTime=false;
		} else {*/velocity.x = oldSpeed; //System.out.println ("OldSPeed = " + oldSpeed);}
		//}
		//System.out.println ("Velocita' = " + velocity.x);
		//System.out.println (firstTime);
		
		
		if(velocity.y > speed)
			velocity.y = speed; //la velocita' non puo' andare oltre a speed
		else if(velocity.y < -speed)
			velocity.y = -speed;
		
		//salva le vecchie posizioni
		//float oldX = getX();
		float oldY = getY();
		//settiamo due valori booleani: uno per vedere se collidiamo nell'asse X, uno per l'asse Y
		//boolean collisionX = false;
		boolean collisionY = false;

		// muovi in x
		setX(getX() + velocity.x * delta);

		// calculate the increment for step in #collidesLeft() and #collidesRight()
		increment = collisionLayer.getTileWidth();
		increment = getWidth() < increment ? getWidth() / 2 : increment / 2;

		// muovi in Y
		setY(getY() + velocity.y * delta * 5f);

		// calculate the increment for step in #collidesBottom() and #collidesTop()
		increment = collisionLayer.getTileHeight();
		increment = getHeight() < increment ? getHeight() / 2 : increment / 2;

		if(velocity.y < 0){ // stai andando giu'
			collisionY = collidesBottom();

		}
		else if(velocity.y > 0) // stai andando su
			collisionY = collidesTop();

		// gestisci la collisione in Y
		if(collisionY) {
			setY(oldY);
			velocity.y = 0;
		}
		
//------------------------
		
		boolean pathX = false;
		
		if(velocity.x < 0) // stai andando a sinistra
			pathX = collidesLeftTest();
		else if(velocity.x > 0) // stai andando a destra
			pathX = collidesRightTest();
		
		if (pathX){
			//setX(oldX - velocity.x*delta);
			//cambiadirezione
			//setX(oldX);
			//TODO Aggiungere suono quando sbatte contro un ostacolo e cambia direzione
			if (velocity.x < 0){
			velocity.x = speed;
			this.oldSpeed = velocity.x;
			setX(getX() + velocity.x * delta);
			//System.out.println (velocity.x);
			}
			else if (velocity.x > 0){
				velocity.x = -speed;
				this.oldSpeed = velocity.x;
				setX(getX() + velocity.x * delta);
				//System.out.println (velocity.x);
				}
		}
		
		//aggiorna l'animazione
		animationTime += delta;
		setRegion(velocity.x < 0 ? left.getKeyFrame(animationTime) : velocity.x > 0 ? right.getKeyFrame(animationTime) : still.getKeyFrame(animationTime));	
		this.oldSpeed = velocity.x;
		//System.out.println ("FINE: Velocita' = " + velocity.x);
		
		guscioCollisionWithEnemy();
		
	}//update
	
	protected Rectangle rectangle() {
		return new Rectangle(this.getX(), this.getY(), this.getWidth(), this.getHeight());
	}//rectangle
	
	protected void guscioCollisionWithEnemy() {
		Array<Goomba> goombas = Play.getEnemies();
		Rectangle guscioRect = rectangle();
		guscioRect.set(this.getX(), this.getY(), this.getWidth(), this.getHeight());
		for(Goomba goomba : goombas) {
			Rectangle eRect = goomba.rectangle();
			if(eRect.overlaps(guscioRect)) {
				if (! goomba.getDeadState() && velocity.x!=0){
					goomba.deadByTrample();
					
				}//if !goomba.deadstate
			}// if erect goombas
		}//for goombas
	}
	
	public void startMoving() { 
		if (player.getVelocity().x > 0 ||  !player.getsx())
			oldSpeed = 150;
		else
			oldSpeed = -150;
	}//startMoving

	public void stopMoving() { 
		oldSpeed = 0;
	}//stopMoving
	


	//METODI DI COLLISIONE
	private boolean isCellMushBlocked(float x, float y) {
		Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
		return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(mushBlockedKey);
	}//isCellMushBlocked
	
	private boolean isCellBlocked(float x, float y) {
		Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
		return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(blockedKey);
	}//isCellBlocked

	public boolean collidesRight() {
		for(float step = 0; step < getHeight(); step += increment)
			if(isCellBlocked(getX() + getWidth(), getY() + step))
				return true;
		return false;
	}//collidesRIght

	public boolean collidesLeft() {
		for(float step = 0; step < getHeight(); step += increment)
			if(isCellBlocked(getX(), getY() + step))
				return true;
		return false;
	}//collidesLeft

	public boolean collidesLeftTest() {
		for(float step = 0; step < getHeight(); step += increment)
			if(isCellMushBlocked(getX(), getY() + step))
				return true;
		return false;
	}//collidesLeftTest
	
	public boolean collidesRightTest() {
		for(float step = 0; step < getHeight(); step += increment)
			if(isCellMushBlocked(getX() + getWidth(), getY() + step))
				return true;
		return false;
	}//collidesRightTest

	public boolean collidesTop() {
		for(float step = 0; step <getWidth(); step += increment)
			if(isCellBlocked(getX() + step, getY() + getHeight())){
				return true;
			}
		return false;
	}//collidesTop

	public boolean collidesBottom() {
		for(float step = 0; step < getWidth(); step += increment)
			if(isCellBlocked(getX() + step , getY() ))
				return true;
		return false;

	}//collidesBottom
	
	//METODI GETTERS
	public TiledMapTileLayer getCollisionLayer() {
		return collisionLayer;
	}//getCollisionLayer
	public boolean getDeadState() {
		return deadState;
	}//getDeadState
	public void setDeadState() {
		velocity.set(0,0);
		deadState = true;
	}//setDeadState
	public Vector2 getVelocity(){
		return velocity;
	}

}//OneUP
